/*
 * algorithm write by Igor Sysoev.
 */
#ifndef WLIB_CORE_WTK_HEAP_H_
#define WLIB_CORE_WTK_HEAP_H_
#include "wtk/core/wtk_type.h"
#include "wtk_alloc.h"
#include "wtk_queue.h"
#include "wtk_str.h"
#ifdef __cplusplus
extern "C" {
#endif
struct wtk_array;
#define WTK_HEAP_ALIGNMENT       16
//#define WTK_ALIGNMENT   sizeof(unsigned long)    /* platform word */
#define WTK_MAX_ALLOC_FROM_HEAP  (4096 - 1)
#define wtk_heap_dup_string_s(h,s)  wtk_heap_dup_string(h,s,sizeof(s)-1)
typedef struct wtk_heap wtk_heap_t;
typedef struct wtk_heap_block wtk_heap_block_t;
typedef struct wtk_heap_large wtk_heap_large_t;

struct wtk_heap_block
{
	uint8_t 	*first;
	uint8_t 	*last;
	uint8_t 	*end;
	wtk_heap_block_t *next;
	unsigned int failed;
};

struct wtk_heap_large
{
	struct wtk_heap_large *next;
	void *data;
	int size;
};

struct wtk_heap
{
	wtk_heap_block_t *first;
	size_t 	max;
	size_t	size;
	size_t align;
	wtk_heap_block_t *current;
	wtk_heap_large_t *large;
};

/**
 *	@brief create heap;
 */
wtk_heap_t* wtk_heap_new(size_t size);

/**
 *  @brief align heap with specify alignment;
 */
wtk_heap_t* wtk_heap_new2(size_t size,int align_size);

/**
 * @brief bytes of heap occupied;
 */
int wtk_heap_bytes(wtk_heap_t *heap);

/**
 * @brief release heap memory.
 */
int wtk_heap_delete(wtk_heap_t* heap);

/**
 * @brief reset heap,free all large memory.
 */
int wtk_heap_reset(wtk_heap_t* heap);

/**
 * @brief reset heap,and all memory is not freed;
 */
int wtk_heap_reset2(wtk_heap_t* heap);

/**
 * @brief allocate memory with size bytes from heap.
 */
void* wtk_heap_malloc(wtk_heap_t* heap,size_t size);

/**
 * @brief allocate from heap and set zero.
 */
void* wtk_heap_zalloc(wtk_heap_t* heap,size_t size);

/**
 * @brief duplicate wtk_string_t;
 */
wtk_string_t* wtk_heap_dup_string(wtk_heap_t *h,const char *s,int sl);

/**
 * @return string with 0 end.
 */
wtk_string_t* wtk_heap_dup_string2(wtk_heap_t *h,const char *s,int sl);

/**
 * @brief return string will '\0' end.
 */
char *wtk_heap_dup_str(wtk_heap_t *heap,const char* s);

/**
 * @brief return string will '\0 end with string;
 */
char* wtk_heap_dup_str2(wtk_heap_t *heap,const char *data,int len);

/**
 * @brief duplicate data;
 */
char* wtk_heap_dup_data(wtk_heap_t *h,const char *s,int l);

/**
 * @brief print heap;
 */
void wtk_heap_print(wtk_heap_t *heap);

/**
 * @brief fill string with data;
 */
void wtk_heap_fill_string(wtk_heap_t *heap,wtk_string_t *str,char *data,int bytes);


struct wtk_array* wtk_utf8_string_to_chars(wtk_heap_t *heap,char *data,int bytes);

void wtk_heap_add_large(wtk_heap_t *heap,char *p,int size);
//=================== Test Section ==================
void wtk_heap_test_g();
#ifdef __cplusplus
};
#endif
#endif
